class Promis{
    //准备
    static PENDING = 'pending';
    //解决
    static FULFILLED = 'fulfilled';
    //拒绝
    static REJECTED = 'rejected';

    constructor(executor){
        this.status = Promis.PENDING;
        this.value = null;
        this.callbacks = [];
        try{
            //改变当前this指向
            executor(this.resolve.bind(this),this.reject.bind(this))
        }catch(e){
            //执行者报错，也认为是被拒绝
            this.reject(e);
        }
    }

    resolve(value){
        //状态一旦被改变，则不能再次被改变
        if(this.status == Promis.PENDING){
            this.status = Promis.FULFILLED;
            this.value = value;
            this.callbacks.forEach(callback=>{
                callback.onFulfilled(this.value);
            })
        }
    }

    reject(reason){
        if(this.status == Promis.PENDING){
            this.status = Promis.REJECTED;
            this.value = reason;
            this.callbacks.forEach(callback=>{
                callback.onRejected(this.value);
            })
        }
    }

    then(onFulfilled,onRejected){
        typeof onFulfilled != 'function' && (onFulfilled = value=> value)
        typeof onRejected != 'function' && (onRejected = e => {throw e})
        let promise = new Promis((resolve,reject)=>{
            setTimeout(()=>{
                //解决异步执行
                if(this.status == Promis.PENDING){
                    this.callbacks.push({
                        onFulfilled:value=>{
                            try{
                                let x = onFulfilled(value);
                                Promis.resolvePromise(promise,x,resolve,reject)
                            }catch(e){
                                reject(e)
                            }
                        }
                        ,onRejected:reason=>{
                            try{
                                let x = onRejected(reason);
                                Promis.resolvePromise(promise,x,resolve,reject)
                            }catch(e){
                                reject(e)
                            }
                        }
                    })
                }
                if(this.status == Promis.FULFILLED){
                    try{
                        let x = onFulfilled(this.value);
                        Promis.resolvePromise(promise,x,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                }
                if(this.status == Promis.REJECTED){
                    try{
                        let x = onRejected(this.value);
                        Promis.resolvePromise(promise,x,resolve,reject);
                    }catch(e){
                        reject(e)
                    }
                }
            })
        });
        return promise;
    }

    static resolvePromise(promise,x,resolve,reject){
        if(promise == x){
            throw TypeError("chaining circle");
        }
        if(x instanceof Promis){
            x.then(value=>{
                //如果resolve函数又返回一个Promise
                Promis.resolvePromise(promise,value,resolve,reject)
            },reason=>{
                reject(reason);
            });
        }else{
            resolve(x);
        }
    }

    static resolve(value){
        return new Promis((resolve,reject)=>{
            resolve(value);
        })
    }

    static reject(reason){
        return new Promis((resolve,reject)=>{
            reject(reason);
        })
    }

    catch(onReject){
        return this.then(null,onReject);
    }
	
	finally(executor){
		this.then(()=>{
			executor();
		}).catch(()=>{
			executor();
		})
	}

    //并发执行多个promise，有个是失败的则全部失败
    static all(promises){
        if(!Array.isArray(promises)){
            throw TypeError("promises must be a array");
        }
        let result = [],times = 0;
        let processData = function(value,i,resolve){
            result[i] = value;
            times++;
            if(times == promises.length){
                resolve(result);
            }
        }
        return new Promis((resolve,reject)=>{
            promises.forEach((promise,i)=>{
                if(promise instanceof Promis){
                    promise.then(value=>{
                        processData(value,i,resolve);
                    },reason=>{
                        reject(reason);
                    })
                }else{
                    processData(promise,i,resolve);
                }
            })
        })
    }

    //处理多个并发请求，采用最快的（谁先完成用谁的）
    static race(promises){
        return new Promis((resolve,reject)=>{
            promises.forEach(promise=>{
                if(promise instanceof Promis){
                    promise.then(resolve,reject);
                }else{
                    resolve(promise);
                }
            })
        })
    }

    //无论成功还是拒绝都会被执行
    finally(callback){
        return this.then(value=>{
           return Promis.resolve(callback()).then(()=>value)
        },reason=>{
            return Promis.resolve(callback()).then(()=>{throw reason})
        })
    }

    //延迟对象
    static deferred(){
        let dfd = {};
        dfd.promise = new Promis((resolve,reject)=>{
            dfd.resolve = resolve;
            dfd.reject = reject;
        })
        return dfd;
    }

}